# coding:utf-8

import os
import yaml
import requests
import re
import base64
import traceback
from configparser import ConfigParser

"""
觅思文档导出的文集导入觅思文档
"""

# 导入文集
class ImportZipProject():
    def __init__(self):
        self.mrdoc_url = MRDOC_URL
        self.mrdoc_token = MRDOC_TOKEN
        self.base_path = BASE_PATH
        self.toc_item_list = []
        self.toc_id_map = {}
        self.total_doc = 0
        self.total_img = 0

    # 树转列表
    def tree2list(self,item, parent=0):
        i = {
            'id': item['id'],
            'name': item['name'],
            'file': item['file'],
            'editor_mode': item['editor_mode'] if 'editor_mode' in item.keys() else 1,
            'parent': parent,
        }
        if i not in self.toc_item_list and i['id'] != i['parent']:
            # print(1, i)
            self.toc_item_list.append(i)
        if 'children' in item.keys() and len(item['children']) > 0:
            for i in item['children']:
                ci = {
                    'id': i['id'],
                    'name': i['name'],
                    'file': i['file'],
                    'editor_mode': i['editor_mode'] if 'editor_mode' in i.keys() else 1,
                    'parent': item['id']
                }
                if ci not in self.toc_item_list:
                    # print(0,item)
                    self.toc_item_list.append(ci)
                self.tree2list(i, parent=item['id'])

    # 工作方法
    def work(self):
        # 读取yaml文件
        try:
            with open(os.path.join(self.base_path ,'mrdoc.yaml'),'r',encoding='utf-8') as yaml_file:
                yaml_str = yaml.safe_load(yaml_file.read())
                project_name = yaml_str['project_name'] \
                    if 'project_name' in yaml_str.keys() else self.base_path.split('\\')[-1]
                project_desc = yaml_str['project_desc'] if 'project_desc' in yaml_str.keys() else ''
                project_role = yaml_str['project_role'] if 'project_role' in yaml_str.keys() else 1
                editor_mode = yaml_str['editor_mode'] if 'editor_mode' in yaml_str.keys() else 1
                project_toc = yaml_str['toc']
                # print(project_toc)
                for i in project_toc:
                    self.tree2list(i, parent=i['parent_doc'])
                # print(self.toc_item_list)
                # print(len(self.toc_item_list))
                print(">>>发现mrdoc.yaml文件，应用其层级结构为文档层级")
        except:
            print(">>>未发现mrdoc.yaml文件，使用默认文档层级")
            project_name = self.base_path.split('/')[-1]
            project_desc = ''
            project_role = 1
            editor_mode = 1
            project_toc = False
        try:
            # 新建文集
            project_info = {
                'name':project_name,
                'desc':project_desc,
                'role':project_role
            }
            project_created = self.create_project(info=project_info)
            # print(project_created)
            if project_created['status']:
                print("+已新建文集：", project_name)
                project_id = project_created['data']
            else:
                print("[x]新建文集出错，导入终止！")
                raise Exception

            if project_toc is False:
                # 遍历临时文件夹中的所有文件和文件夹
                for f in os.listdir(self.base_path):
                    # 获取 .md 文件
                    if f.endswith('.md'):
                        print(">处理本地文档：",f)
                        # 读取 .md 文件文本内容
                        with open(os.path.join(self.base_path,f),'r',encoding='utf-8') as md_file:
                            doc_content = md_file.read()
                            doc_content = self.convert_doc_img(doc_content)
                            # 新建文档
                            doc_info = {
                                'pid': project_id,
                                'title': f[:-3],
                                'doc': doc_content,
                                'editor_mode': 1,
                            }
                            doc_created = self.create_doc(info=doc_info)
                            if doc_created['status']:
                                self.total_doc += 1
                                print("+已导入文档：",f[:-3])
            else:
                for i in self.toc_item_list:
                    print(">处理本地文档：", i)
                    with open(os.path.join(self.base_path,i['file']),'r',encoding='utf-8') as md_file:
                        doc_content = md_file.read()
                        doc_content = self.convert_doc_img(doc_content)
                        # 新建文档
                        doc_info = {
                            'pid':project_id,
                            'title':i['name'],
                            'doc':doc_content,
                            'editor_mode':i['editor_mode'] if 'editor_mode' in i.keys() else 1,
                            'parent_doc':0 if i['parent'] == 0 else self.toc_id_map[i['parent']]
                        }
                        doc_created = self.create_doc(info=doc_info)
                        if doc_created['status']:
                            self.toc_id_map[i['id']] = doc_created['data']
                            self.total_doc += 1
                            print("+已导入文档：",i['name'])
            print(">>>导入完成！")
            print("导入文档数：",self.total_doc)
            print("转存图片数：",self.total_img)
        except Exception as e:
            print("[x]解析导入文件异常：",repr(e))
            print(traceback.print_exc())

    def convert_doc_img(self,doc):
        # 查找MD语法的静态文件
        pattern = r"\!\[.*?\]\(.*?\)"
        media_list = re.findall(pattern, doc)
        if len(media_list) > 0:
            for media in media_list:
                media_filename = media.split("(")[-1].split(")")[0] # 媒体文件的文件名
                # 存在本地图片路径
                if media_filename.startswith("./") or media_filename.startswith("/"):
                    # 判断本地图片路径是否存在
                    if media_filename.startswith("./"):
                        temp_media_file_path = os.path.join(self.base_path, media_filename[2:])
                    else:
                        temp_media_file_path = os.path.join(self.base_path, media_filename[1:])
                    if os.path.exists(temp_media_file_path):
                        print(">发现本地图片：",media_filename)
                        # 如果存在，上传本地图片
                        is_upload_img = self.upload_img(path=temp_media_file_path)
                        if 'success' in is_upload_img.keys() and is_upload_img['success'] == 1:
                            print("+转存图片成功：", media_filename)
                            self.total_img += 1
                            doc = doc.replace(media_filename, is_upload_img['url'])

        # 查找<img>标签形式的静态图片
        img_pattern = r'<img[^>]*/>'
        img_list = re.findall(img_pattern, doc)
        if len(img_list) > 0:
            for img in img_list:
                media_src = re.findall('src="([^"]+)"', img)
                if len(media_src) > 0:
                    media_filename = media_src[0]
                else:
                    break

                # 存在本地图片路径
                if media_filename.startswith("./") or media_filename.startswith("/"):
                    # 判断本地图片路径是否存在
                    if media_filename.startswith("./"):
                        temp_media_file_path = os.path.join(self.base_path, media_filename[2:])
                    else:
                        temp_media_file_path = os.path.join(self.base_path, media_filename[1:])
                    if os.path.exists(temp_media_file_path):
                        print(">发现本地图片：",media_filename)
                        # 如果存在，上传本地图片
                        is_upload_img = self.upload_img(path=temp_media_file_path)
                        if 'success' in is_upload_img.keys() and is_upload_img['success'] == 1:
                            print("+转存图片成功：", media_filename)
                            self.total_img += 1
                            doc = doc.replace(media_filename, is_upload_img['url'])

        return doc

    # 新建文集
    def create_project(self,info):
        resp = requests.post(self.mrdoc_url + "/api/create_project/?token="+self.mrdoc_token,data=info)
        return resp.json()

    # 新建文档
    def create_doc(self,info):
        resp = requests.post(self.mrdoc_url + "/api/create_doc/?token="+self.mrdoc_token,data=info)
        return resp.json()

    # 上传图片
    def upload_img(self,path):
        with open(path,'rb') as img:
            img_base = base64.b64encode(img.read())
            resp = requests.post(self.mrdoc_url + "/api/upload_img/?token="+self.mrdoc_token,data={"data":img_base})
            # print(resp.json())
            return resp.json()


if __name__ == '__main__':
    print("""
  __  __            _       _                       ___    __  __      _____             
 |  \/  |          | |     | |                     |__ \  |  \/  |    |  __ \            
 | \  / | __ _ _ __| | ____| | _____      ___ __      ) | | \  / |_ __| |  | | ___   ___ 
 | |\/| |/ _` | '__| |/ / _` |/ _ \ \ /\ / / '_ \    / /  | |\/| | '__| |  | |/ _ \ / __|
 | |  | | (_| | |  |   < (_| | (_) \ V  V /| | | |  / /_  | |  | | |  | |__| | (_) | (__ 
 |_|  |_|\__,_|_|  |_|\_\__,_|\___/ \_/\_/ |_| |_| |____| |_|  |_|_|  |_____/ \___/ \___|
                                                                                         
【通用本地 Markdown 文档导入到觅思文档】 v20231025
* 支持觅思文档内导出的文集文件；
* 支持按层级导入；
* 支持本地图片转存；
    """)
    CONFIG = ConfigParser()
    CONFIG.read(os.path.join('./config.ini'), encoding='utf-8')

    MRDOC_URL = CONFIG.get("mrdoc","url",fallback="")
    if MRDOC_URL == "":
        MRDOC_URL = input("1)请输入你的觅思文档地址:")
    else:
        print("1)你配置的觅思文档地址为：",MRDOC_URL)
    if MRDOC_URL.endswith("/"):
        MRDOC_URL = MRDOC_URL[:-1]

    MRDOC_TOKEN = CONFIG.get("mrdoc", "token", fallback="")
    if MRDOC_TOKEN == "":
        MRDOC_TOKEN = input("2)请输入你的觅思文档用户 Token:")
    else:
        print("2)你配置的觅思文档用户Token为:",MRDOC_TOKEN)

    BASE_PATH = CONFIG.get("mrdoc", "dir", fallback="")
    if BASE_PATH == "":
        BASE_PATH = input("3)请输入待导入文件夹路径:")
    else:
        print("3)你配置的待导入文件夹路径为:",BASE_PATH)

    if os.path.exists(BASE_PATH):
        op = ImportZipProject()
        op.work()
    else:
        print("[x]错误：目标文件夹不存在！")
    os.system('pause')

